/* Copyright (c) Soon.Liao 2024. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * Create Date : 2024
 * @Date: 2024-10-14 07:57:06
 * @LastEditors: soon.liao
 * @LastEditTime: 2024-10-26 14:11:44
 * @FilePath: /src/application/ws63/rgb_master/wifi/web_server.c
 * @Description: NA
 * NA
 */
#include "stdlib.h"
#include "app_init.h"
#include "soc_osal.h"
#include "lwip/sockets.h"
#include "nv_common_cfg.h"
#include "hal_reboot.h"
#include "cJSON.h"
#include "cmd_json.h"
#include "key_value.h"
#include "html_page.h"
#include "web_server.h"

#define RGB_MASTER_WEB_SERVER_LOG "[WEB_SERVER]"

#define WEB_SERVER_PORT 80

#define CHAR_G 'G'
#define CHAR_E 'E'
#define CHAR_T 'T'
#define CHAR_F_SLASH '/'
#define CHAR_P 'P'
#define CHAR_O 'O'
#define CHAR_S 'S'
#define CHAR_SPACE ' '
#define CHAR_END '\0'

#define HTTP_MOTHOD_CHAR_INDEX_0 0
#define HTTP_MOTHOD_CHAR_INDEX_1 1
#define HTTP_MOTHOD_CHAR_INDEX_2 2
#define HTTP_MOTHOD_CHAR_INDEX_3 3
#define HTTP_MOTHOD_CHAR_INDEX_4 4

static int g_sockfd = NULL;
static int g_connfd = -1;

static char *g_json_str[1024];

static int g_led_count_value = 10;
static int g_brightness_value = 10;

static int http_message_type(char *buf)
{
    int buflen = strlen(buf);
    /* 判断是不是HTTP的GET命令 */
    if (buf[HTTP_MOTHOD_CHAR_INDEX_0] == CHAR_G && buf[HTTP_MOTHOD_CHAR_INDEX_1] == CHAR_E &&
        buf[HTTP_MOTHOD_CHAR_INDEX_2] == CHAR_T && buf[HTTP_MOTHOD_CHAR_INDEX_3] == CHAR_SPACE &&
        buf[HTTP_MOTHOD_CHAR_INDEX_4] == CHAR_F_SLASH) {
        return 0;
    } else if (buf[HTTP_MOTHOD_CHAR_INDEX_0] == CHAR_P && buf[HTTP_MOTHOD_CHAR_INDEX_1] == CHAR_O &&
               buf[HTTP_MOTHOD_CHAR_INDEX_2] == CHAR_S && buf[HTTP_MOTHOD_CHAR_INDEX_3] == CHAR_T) {
        return 1;
    }
    return -1;
}

// 创建JSON格式的响应数据
char *create_json_response(char *key, int value)
{
    char *json_template = "{\"%s\": %d}";
    int key_len = strlen(json_template) + strlen(key) + 10; // 10 for int value
    char *json_response = (char *)malloc(key_len);
    if (json_response == NULL) {
        return NULL;
    }
    snprintf(json_response, key_len, json_template, key, value);
    return json_response;
}

char *find_json_in_html(char *input)
{
    char *start = strstr(input, "{");
    char *end = strstr(input, "}");
    if (start && end) {
        int length = end - start + 1;
        strncpy(g_json_str, start, length);
        g_json_str[length + 1] = CHAR_END;
        osal_printk("\r\nJSON data: %s\r\n", g_json_str);
        return g_json_str;
    } else {
        osal_printk("\r\nJSON data not found.\r\n");
        return NULL;
    }
}

static void parse_http_message_get_type(char *request)
{
    ssize_t retval = 0;
    if (strstr(request, HTML_CMD_STR_GET_LED_NUM)) {
        osal_printk("\r\n%s is_get_led_num response \r\n", __FUNCTION__);
        uint16_t kvalue_length;
        uint8_t kvalue;
        int ret = key_value_rgb_master_led_number_read(&kvalue, &kvalue_length);
        g_led_count_value = kvalue;
        osal_printk("\r\n%s g_led_count_value=%d \r\n", __FUNCTION__, g_led_count_value);
        char *response = create_json_response("ledCount", g_led_count_value);
        if (response != NULL) {
            retval = send(g_connfd, response, strlen(response), 0);
            osal_printk("\r\n%s is_get_led_num response=%s\r\n", __FUNCTION__, response);
            free(response);
            if (retval <= 0) {
                osal_printk("GET method send response failed 2, %ld!\r\n", retval);
                lwip_close(g_sockfd);
            }
        }
    } else if (strstr(request, HTML_CMD_STR_GET_BRIGHTNESS) != NULL) {
        osal_printk("\r\n%s is_get_brightness response \r\n", __FUNCTION__);
        uint16_t kvalue_length;
        uint8_t kvalue;
        int ret = key_value_rgb_master_led_brightness_read(&kvalue, &kvalue_length);
        osal_printk("\r\n%s is_get_brightness ret=0x%x kvalue=%d kvalue_length=%d\r\n", __FUNCTION__, ret, kvalue,
                    kvalue_length);
        g_brightness_value = kvalue;
        osal_printk("\r\n%s g_brightness_value=%d \r\n", __FUNCTION__, g_brightness_value);
        char *response = create_json_response("brightness", g_brightness_value);
        if (response != NULL) {
            retval = send(g_connfd, response, strlen(response), 0);
            osal_printk("\r\n%s is_get_brightness response=%s\r\n", __FUNCTION__, response);
            free(response);
            if (retval <= 0) {
                osal_printk("GET method send response failed 3, %ld!\r\n", retval);
                lwip_close(g_sockfd);
            }
        }
    } else {
        osal_printk("\r\n%s action not found in request default page.\r\n", __FUNCTION__);
        retval = send(g_connfd, HTTP_HOME_PAGE_HTML, strlen(HTTP_HOME_PAGE_HTML), 0);
        if (retval <= 0) {
            osal_printk("GET method send response failed 4, %ld!\r\n", retval);
            lwip_close(g_sockfd);
        }
    }
}

static void http_message_get_type(char *request)
{
    ssize_t retval = 0;

    retval = send(g_connfd, HTTP_HTML_HDR, strlen(HTTP_HTML_HDR), 0);
    if (retval <= 0) {
        osal_printk("GET method send response failed 1, %ld!\r\n", retval);
        lwip_close(g_sockfd);
    }
    parse_http_message_get_type(request);
}

void handle_clear_wifi(void)
{
    osal_printk("\r\n%s is_clear_wifi\r\n", RGB_MASTER_WEB_SERVER_LOG);
    rgb_master_wifi_info_t clear_wifi_info;
    (void)memset_s(&clear_wifi_info, sizeof(clear_wifi_info), 0, sizeof(clear_wifi_info));
    int ret = key_value_rgb_master_wifi_info_write((uint8_t *)&clear_wifi_info, sizeof(clear_wifi_info));
    osal_mdelay(NV_WRITE_DELAY_TIME_MS);
    osal_printk("Clear Wifi Info reboot\n");
    hal_reboot_chip();
}
static void handle_submit_wifi(char *request)
{
    char *tmp_data_str = find_json_in_html(request);
    if (tmp_data_str == NULL) {
        osal_printk("\r\n%s Can't fine SSID,Password\n\r", __FUNCTION__);
        return;
    }
    parse_json_wifi_info(tmp_data_str);
}

static void handle_submit_led_num(char *request)
{
    char *tmp_data_str = find_json_in_html(request);
    if (tmp_data_str == NULL) {
        osal_printk("\r\n%s Can't find ledCount\n\r", __FUNCTION__);
        return;
    }
    parse_json_wifi_led_num(tmp_data_str);
}

static void handle_submit_brightness(char *request)
{
    char *tmp_data_str = find_json_in_html(request);
    if (tmp_data_str == NULL) {
        osal_printk("\r\n%s Can't find brightness_data_str\n\r", __FUNCTION__);
        return;
    }
    parse_json_wifi_brightness(tmp_data_str);
}

void handle_toggle_led(void)
{
    osal_printk("\r\nCMD = %s \r\n", CMD_TOGGLE_LED);
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_SERVER)
    create_json_wifi_cammand(CMD_TOGGLE_LED);
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_CLIENT)
    rgb_led_strip_toggle();
#endif
}

void handle_prev_mode(void)
{
    osal_printk("\r\nCMD = %s \r\n", CMD_PREV_MODE);
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_SERVER)
    create_json_wifi_cammand(CMD_PREV_MODE);
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_CLIENT)
    rgb_led_strip_perv_mode();
#endif
}
void handle_next_mode(void)
{
    osal_printk("\r\nCMD = %s \r\n", CMD_NEXT_MODE);
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_SERVER)
    create_json_wifi_cammand(CMD_NEXT_MODE);
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_CLIENT)
    rgb_led_strip_next_mode();
#endif
}

void handle_prev_sence(void)
{
    osal_printk("\r\nCMD = %s \r\n", CMD_PREV_SENCE);
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_SERVER)
    create_json_wifi_cammand(CMD_PREV_SENCE);
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_CLIENT)
    rgb_led_strip_perv_sence();
#endif
}
void handle_next_sence(void)
{
    osal_printk("\r\nCMD = %s \r\n", CMD_NEXT_SENCE);
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_SERVER)
    create_json_wifi_cammand(CMD_NEXT_SENCE);
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_CLIENT)
    rgb_led_strip_next_sence();
#endif
}

void handle_start_sle(void)
{
    osal_printk("\r\nCMD = %s\r\n", HTML_CMD_STR_START_SLE);
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_SERVER)

#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_CLIENT)

#endif
}

void handle_clear_sle_info(void)
{
    osal_printk("\r\nCMD = %s\r\n", HTML_CMD_STR_CLEAR_SLE);
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_SERVER)

#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_RGB_MASTER_CLIENT)

#endif
}
static void parse_http_message_post_type(char *request)
{
    if (strstr(request, HTML_CMD_STR_SUBMIT_WIFI) != NULL) { // 找到 submitWiFi 参数的起始位置
        handle_submit_wifi(request);
    } else if (strstr(request, HTML_CMD_STR_SUBMIT_LED_NUM) != NULL) { // 找到 submitLEDCount 参数的起始位置
        handle_submit_led_num(request);
    } else if (strstr(request, HTML_CMD_STR_SET_BRIGHTNESS) != NULL) { // 找到 setBrightness 参数的起始位置
        handle_submit_brightness(request);
    } else if (strstr(request, HTML_CMD_STR_TOGGLE_LED) != NULL) {
        handle_toggle_led();
    } else if (strstr(request, HTML_CMD_STR_PREV_MODE) != NULL) {
        handle_prev_mode();
    } else if (strstr(request, HTML_CMD_STR_NEXT_MODE) != NULL) {
        handle_next_mode();
    } else if (strstr(request, HTML_CMD_STR_PREV_SENCE) != NULL) {
        handle_prev_sence();
    } else if (strstr(request, HTML_CMD_STR_NEXT_SENCE) != NULL) {
        handle_next_sence();
    } else if (strstr(request, HTML_CMD_STR_CLEAR_WIFI) != NULL) {
        handle_clear_wifi();
    } else if (strstr(request, HTML_CMD_STR_START_SLE) != NULL) {
        handle_start_sle();
    } else if (strstr(request, HTML_CMD_STR_CLEAR_SLE) != NULL) {
        handle_clear_sle_info();
    } else {
        osal_printk("\r\n%s action not found in request.\r\n", __FUNCTION__);
    }
}

static void http_message_post_type(char *request)
{
    // post请求
    ssize_t retval = 0;
    parse_http_message_post_type(request);
    retval = send(g_connfd, HTTP_HTML_HDR, strlen(HTTP_HTML_HDR), 0);
    if (retval <= 0) {
        osal_printk("POST method send response failed 1, %ld!\r\n", retval);
        lwip_close(g_sockfd);
    }
    retval = send(g_connfd, HTTP_HOME_PAGE_HTML, strlen(HTTP_HOME_PAGE_HTML), 0);
    if (retval <= 0) {
        osal_printk("POST method send response failed 2, %ld!\r\n", retval);
        lwip_close(g_sockfd);
    }
}

void web_server_init(void)
{
    // 建立tcp连接
    ssize_t retval = 0;
    int backlog = 1;
    g_sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
    g_connfd = -1;
    struct sockaddr_in clientAddr = {0};
    socklen_t clientAddrLen = sizeof(clientAddr);
    struct sockaddr_in serverAddr = {0};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(WEB_SERVER_PORT);   // 端口号，从主机字节序转为网络字节序
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 允许任意主机接入， 0.0.0.0
    retval = bind(g_sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); // 绑定端口
    if (retval < 0) {
        osal_printk("bind failed, %ld!\r\n", retval);
        lwip_close(g_sockfd);
    }
    osal_printk("bind to port %u success!\r\n", WEB_SERVER_PORT);
    retval = listen(g_sockfd, backlog); // 开始监听
    if (retval < 0) {
        osal_printk("listen failed!\r\n");
        lwip_close(g_sockfd);
    }
    osal_printk("listen with %d backlog success!\r\n", backlog);
    while (1) {
        static int i = 1;
        g_connfd = accept(g_sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen);
        if (g_connfd < 0) {
            osal_printk("accept failed, %d, %d\r\n", g_connfd, errno);
            lwip_close(g_sockfd);
        }
        char request[1024] = "";
        retval = recv(g_connfd, request, sizeof(request), 0);
        if (retval < 0) {
            osal_printk("recv request failed, %ld!\r\n", retval);
            lwip_close(g_sockfd);
        }
        int messagetype = http_message_type(request);
        if (messagetype == 0) { // get请求
            http_message_get_type(request);
        } else if (messagetype == 1) { // post请求
            http_message_post_type(request);
        } else { // 未知消息
            osal_printk("Unkonwn :recv request%s\n", request);
        }
        /* 关闭 */
        lwip_close(g_connfd);
    }
}